MessagingService daily shop?

I am trying to create a daily and weekly shop, as in Apex Legends or Fortnite (Thank you everyone for the help! Learn something new everyday!)

The issue I am having, I want the servers to automatically choose the item to be sold and this to be random, but using the service to have all the servers, well have the same item.

I want the item to be randomly picked, and it to be unique every 24 hours. I can have it updated and checked per time, per the loop of the game. Now, what if two servers both try to update it, or if I have the very first server up to host it. What if that shuts down?

If a new server was to open, does the subscription automatically check upon the server’s creation and setting the function?

I am very unfamiliar with how this system works, and where to start. I don’t want to run my own server or anything to handle that, and want it to be across servers.

How would I start with this, and have it be efficient I have been trying to think of different ways but can’t seem to find a good place to start.

Just think of the Fortnite shop, and how the 24 hours system happens. Except the servers running determine the item across all of the servers. Now, how do I prevent all the servers trying to update and change it, and how does the subscription system work with new games?

I am asking for advice and where to start and handle this, some code example would help and maybe details to how exactly the system and stuff works, and I don’t want to run my own server and don’t want to set the items manually.

2 Likes

MessagingService doesn’t seem necessary if you want to create a weekly shop. If the servers choose the item randomly, then you can use some sort of synchronized time as the seed to generate it with.

For example, since the unix timestamp (as of writing this) is 1554014511, and the number of seconds in a week is 604800, then you would use floor(1554014511/604800) as your shop’s seed. as long as your server times are synchronized, your weekly shop will generate a new set of items exactly every week.

2 Likes

How would I go about making it exactly the same items for every server on that day…? Do I have to create a type of code per item, as I’m just trying to make it random and determine it on it’s own, and my initial idea was to have the server get a random one, and then update all of the other servers with that item. The issue is I’m not gonna run my own server, or anything to be up to update the servers.

I have no issue working with the time and settings that up, just settings up the system to have all the server. Have the same exact item, that is randomly chosen, and not using my own server or any preset information.

If the items are randomly generated and you use the exact same seed for every server, then wouldn’t it follow that every server would have the same items?

Are you able to be more specific with what you’re implying, I’m a bit tired at the moment and not quite following you.

How are you generating items right now? You are generating them randomly, right?

Just math.random with the current items per rarity;

Random math for rarity > pick table > random one in table > item

What tables that are available are based off os.time

What @XAXA is saying is you probably want to use Random.new for randomness and use time as the seed since time is globally available in all servers. This way you’ll see the same result in all servers.

1 Like

I’m honestly trying to mess with this, but say you have two scripts in the same game. ServerScriptService on startup, how would I get them to print the same numbers (random) in the same order? Like the first print is 1, the 2nd is 8 and etc…

From my understanding is you set the randomseed to the os.time

local seed = os.time()
math.randomseed(seed)

print(math.random(seed/604800))

I honestly can’t think right now, so I’m sorry for being inconvenient but I am really thankful for the help so far.

Don’t use math.randomseed as this globally modifies the seed.

Secondly Random.new offers useful functions for you.
NextInteger will be useful for selecting shop items.

If #seconds in a week is 604800 then you can divide by 604800 and floor your result to get the number of weeks since the epoch instead of seconds. math.floor(os.time()/604800)

Edit:
Since you’re looking for every week use your weeks since epoch as the seed. NextInteger allows you to use a max and min so you can use local item = shopItems[random:NextInteger(1, #shopItems)]

Use Random.new(seed). Every Random object initialized with the same seed will generate the same sequence of numbers.

local r1 = Random.new(1234)
-- I *guarantee* this will output these numbers if you run this yourself:
-- 0.10645921279869 
-- 0.64572802332265
-- 0.47714277796746
print(r1:NextNumber(), r1:NextNumber(), r1:NextNumber())
1 Like

What you could also do, is have a webhost where you store json data of the shop. Then when the timestamp is equal or greater than the next week timestamp, you can update the game shop based on the response data.

Hosting a server is out of the question.


1 Like

In that case a datastore is just as good if not better since it’s in game, faster, and free.

1 Like
local seed = math.floor(os.time()/(3600*24*7))
local ran = Random.new(seed)
print(ran:NextNumber().."\n"..ran:NextNumber().."\n"..ran:NextNumber())

This code will generate a pseudorandom sequence of numbers that changes every Thursday at 00:00, so servers have no need to communicate with each other as long as the code used to generate the offers are the same.

For example:

local offerList = {"ItemA", "ItemB", "ItemC", "ItemD", "ItemE"}
function getShopItems(seed)
	local ran = Random.new(seed)
	local weeklyOffer = {}
	for i = 1, 3 do
		table.insert(weeklyOffer, 1, offerList[ran:NextInteger(1, #offerList)])
		ran:NextNumber()
	end
	return weeklyOffer
end

local seed = math.floor(os.time()/(3600*24*7)+4/7) --The seed should now change every Monday instead of every thursday
local weeklyOffer = getShopItems(seed)

for _, v in pairs(weeklyOffer) do
	print(v)
end
5 Likes

Please feel free to correct me if I did the date wrong, but I believe this is how you add a day to os.time

local uptime = os.time()+60 * 60 * 24 --the extra time

local r1 = Random.new(math.floor(uptime/86400))
local r2 = Random.new(math.floor(os.time()/86400))

print(math.floor(os.time()/86400)) --Current time
print(math.floor(uptime/86400)) --Current time + a day and some just to see if I get a different result

local shopItems = {}

-- Pretty much a folder full of whatever you want
for i,v in pairs(game:GetService("ServerStorage"):WaitForChild("Modules"):GetChildren()) do
	table.insert(shopItems,v)
end

local item = shopItems[r1:NextInteger(1, #shopItems)] --You can just switch r1 for r2 to check the result

print(item)

This seems to work, albeit sloppy, feel free to correct me and advice is always welcome

Adjusting the date is quite cool.

 local currentdate = os.time()+60 * 60 * 24 * 7

The only issue is duplicate items, as with the above code. To which you could probably just do the next thing again and check that. Really cool though, and am I doing the time/dates right?

Offsetting the date by a whole week won’t do anything for you if you are going to change the offers weekly.

local dayOffset = 4 -- 0 = Thursday, 1 = Friday, 2 = Saturday, 3 = Sunday, 4 = Monday, etc.
local currentdate = os.time()+60 * 60 * 24 * dayOffset
local seed = math.floor(currentdate / (60 * 60 * 24 * 7))

Something you should be careful about is when you want to update the code used to generate your weekly offers as this would result in your weekly offers suddenly changing within the week (which may result in unhappy players) and inconsistent weekly offers across your servers as there might be older servers still up that are running an older version of your code.
Something you could do to fix this:

function getWeeklyOfferOld(seed) --uses the old code to generate weekly offers
	local offerList = {"ItemA", "ItemB", "ItemC", "ItemD", "ItemE"}
	local ran = Random.new(seed)
	local weeklyOffer = {}
	for i = 1, 3 do
		table.insert(weeklyOffer, 1, offerList[ran:NextInteger(1, #offerList)])
		ran:NextNumber()
	end
	return weeklyOffer
end

function getWeeklyOffer(seed)
	local dontUseBeforeWeek = 2572 -- use the old code before the 7th of April 2019, give roblox 1-2 weeks to phase out your older servers
	if seed < dontUseBeforeWeek then
		return getWeeklyOfferOld(seed)
	end
	
	local offerList = {"ItemA", "ItemB", "ItemC", "ItemD", "ItemE", "ItemF"}
	local ran = Random.new(seed)
	local weeklyOffer = {}
	for i = 1, 3 do
		table.insert(weeklyOffer, 1, offerList[ran:NextInteger(1, #offerList)])
		ran:NextNumber()
	end
	return weeklyOffer
end

local dayOffset = 4 
local currentdate = os.time()+60 * 60 * 24 * dayOffset
local seed = math.floor(currentdate / (60 * 60 * 24 * dayOffset))

local weeklyOffer = getWeeklyOffer(seed)
for _, v in pairs(weeklyOffer) do
	print(v)
end
8 Likes
local currentdate = os.time()+60 * 60 * 24 * 7

No, me doing that is to check the result across the days and how it is overall.

Also, typically I release my stuff in large updates. The smaller things are usually something that wouldn’t affect something like this, but thanks for bringing it to my attention as I didn’t think about it.

@Flostrus will that code sync items across all servers?


Is it possible to use 86400%os.time() and check if it’s equal to 0?