468 lines
12 KiB
JavaScript
468 lines
12 KiB
JavaScript
/**
|
|
* MULTIPLAYER & SOCIAL SYSTEM
|
|
* Co-op mode, trading, leaderboards, and social features
|
|
*/
|
|
class MultiplayerSocialSystem {
|
|
constructor(scene) {
|
|
this.scene = scene;
|
|
this.enabled = true;
|
|
|
|
// Multiplayer
|
|
this.isHost = false;
|
|
this.isConnected = false;
|
|
this.players = new Map();
|
|
this.maxPlayers = 4;
|
|
|
|
// Trading
|
|
this.tradeOffers = new Map();
|
|
this.activeTrade = null;
|
|
|
|
// Leaderboards
|
|
this.leaderboards = new Map();
|
|
|
|
// Social
|
|
this.friends = new Set();
|
|
this.gifts = [];
|
|
|
|
// Events
|
|
this.activeEvent = null;
|
|
|
|
this.loadProgress();
|
|
this.init();
|
|
|
|
console.log('✅ Multiplayer & Social System initialized');
|
|
}
|
|
|
|
init() {
|
|
this.defineLeaderboards();
|
|
this.defineEvents();
|
|
console.log('🌐 Multiplayer & Social ready');
|
|
}
|
|
|
|
// ========== CO-OP MODE ==========
|
|
|
|
hostGame() {
|
|
this.isHost = true;
|
|
this.isConnected = true;
|
|
|
|
// Add host player
|
|
this.players.set('host', {
|
|
id: 'host',
|
|
name: 'Player 1',
|
|
x: 50,
|
|
y: 50,
|
|
isHost: true
|
|
});
|
|
|
|
console.log('🎮 Hosting game...');
|
|
return true;
|
|
}
|
|
|
|
joinGame(hostId) {
|
|
this.isHost = false;
|
|
this.isConnected = true;
|
|
|
|
console.log(`🎮 Joining game ${hostId}...`);
|
|
return true;
|
|
}
|
|
|
|
addPlayer(playerId, playerData) {
|
|
if (this.players.size >= this.maxPlayers) {
|
|
console.log('❌ Game is full');
|
|
return false;
|
|
}
|
|
|
|
this.players.set(playerId, {
|
|
id: playerId,
|
|
name: playerData.name || `Player ${this.players.size + 1}`,
|
|
x: playerData.x || 50,
|
|
y: playerData.y || 50,
|
|
isHost: false
|
|
});
|
|
|
|
console.log(`✅ Player joined: ${playerData.name}`);
|
|
return true;
|
|
}
|
|
|
|
removePlayer(playerId) {
|
|
this.players.delete(playerId);
|
|
console.log(`👋 Player left: ${playerId}`);
|
|
}
|
|
|
|
syncWorldState() {
|
|
// Sync game state between players
|
|
const worldState = {
|
|
time: this.scene.weatherSystem?.currentTime || 0,
|
|
weather: this.scene.weatherSystem?.currentWeather || 'clear',
|
|
players: Array.from(this.players.values())
|
|
};
|
|
|
|
return worldState;
|
|
}
|
|
|
|
updatePlayerPosition(playerId, x, y) {
|
|
const player = this.players.get(playerId);
|
|
if (player) {
|
|
player.x = x;
|
|
player.y = y;
|
|
}
|
|
}
|
|
|
|
// ========== CO-OP QUESTS ==========
|
|
|
|
startCoopQuest(questId) {
|
|
console.log(`🤝 Co-op quest started: ${questId}`);
|
|
|
|
const coopQuests = {
|
|
'farm_together': {
|
|
name: 'Farm Together',
|
|
objective: 'Harvest 100 crops as a team',
|
|
reward: { xp: 500, gold: 1000 }
|
|
},
|
|
'boss_raid': {
|
|
name: 'Boss Raid',
|
|
objective: 'Defeat boss together',
|
|
reward: { xp: 2000, legendary_item: 1 }
|
|
}
|
|
};
|
|
|
|
return coopQuests[questId];
|
|
}
|
|
|
|
// ========== TRADING ==========
|
|
|
|
createTradeOffer(targetPlayerId, offeredItems, requestedItems) {
|
|
const tradeId = `trade_${Date.now()}`;
|
|
|
|
this.tradeOffers.set(tradeId, {
|
|
id: tradeId,
|
|
from: 'local_player',
|
|
to: targetPlayerId,
|
|
offered: offeredItems,
|
|
requested: requestedItems,
|
|
status: 'pending',
|
|
createdAt: Date.now()
|
|
});
|
|
|
|
console.log(`💱 Trade offer created: ${tradeId}`);
|
|
return tradeId;
|
|
}
|
|
|
|
acceptTrade(tradeId) {
|
|
const trade = this.tradeOffers.get(tradeId);
|
|
if (!trade || trade.status !== 'pending') return false;
|
|
|
|
// Execute trade
|
|
this.executeTrade(trade);
|
|
|
|
trade.status = 'completed';
|
|
console.log(`✅ Trade completed: ${tradeId}`);
|
|
return true;
|
|
}
|
|
|
|
rejectTrade(tradeId) {
|
|
const trade = this.tradeOffers.get(tradeId);
|
|
if (!trade) return false;
|
|
|
|
trade.status = 'rejected';
|
|
console.log(`❌ Trade rejected: ${tradeId}`);
|
|
return true;
|
|
}
|
|
|
|
executeTrade(trade) {
|
|
// Transfer items between players
|
|
console.log(`💱 Executing trade...`);
|
|
|
|
// Remove offered items from local player
|
|
if (this.scene.inventorySystem) {
|
|
for (const [item, amount] of Object.entries(trade.offered)) {
|
|
this.scene.inventorySystem.removeItem(item, amount);
|
|
}
|
|
|
|
// Add requested items to local player
|
|
for (const [item, amount] of Object.entries(trade.requested)) {
|
|
this.scene.inventorySystem.addItem(item, amount);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ========== GLOBAL MARKETPLACE ==========
|
|
|
|
listItemOnMarket(item, amount, price) {
|
|
console.log(`🏪 Listed ${amount}x ${item} for ${price} gold`);
|
|
|
|
const listing = {
|
|
id: `listing_${Date.now()}`,
|
|
seller: 'local_player',
|
|
item,
|
|
amount,
|
|
price,
|
|
listedAt: Date.now()
|
|
};
|
|
|
|
return listing;
|
|
}
|
|
|
|
buyFromMarket(listingId) {
|
|
console.log(`💰 Purchased item from market: ${listingId}`);
|
|
}
|
|
|
|
// ========== AUCTION HOUSE ==========
|
|
|
|
createAuction(item, startingBid, duration) {
|
|
console.log(`🔨 Auction created: ${item} starting at ${startingBid} gold`);
|
|
|
|
const auction = {
|
|
id: `auction_${Date.now()}`,
|
|
seller: 'local_player',
|
|
item,
|
|
currentBid: startingBid,
|
|
highestBidder: null,
|
|
endsAt: Date.now() + duration,
|
|
bids: []
|
|
};
|
|
|
|
return auction;
|
|
}
|
|
|
|
placeBid(auctionId, bidAmount) {
|
|
console.log(`💰 Bid placed: ${bidAmount} gold on ${auctionId}`);
|
|
}
|
|
|
|
// ========== PRICE FLUCTUATION ==========
|
|
|
|
updateMarketPrices() {
|
|
// Simulate market price changes
|
|
const priceChanges = {
|
|
wheat: 1.0 + (Math.random() - 0.5) * 0.2,
|
|
iron: 1.0 + (Math.random() - 0.5) * 0.3,
|
|
gold: 1.0 + (Math.random() - 0.5) * 0.1
|
|
};
|
|
|
|
return priceChanges;
|
|
}
|
|
|
|
// ========== LEADERBOARDS ==========
|
|
|
|
defineLeaderboards() {
|
|
this.leaderboards.set('productivity', {
|
|
name: 'Farm Productivity',
|
|
entries: []
|
|
});
|
|
|
|
this.leaderboards.set('speedrun', {
|
|
name: 'Fastest Speedruns',
|
|
entries: []
|
|
});
|
|
|
|
this.leaderboards.set('survival', {
|
|
name: 'Highest Survival Days',
|
|
entries: []
|
|
});
|
|
|
|
this.leaderboards.set('wealth', {
|
|
name: 'Richest Players',
|
|
entries: []
|
|
});
|
|
|
|
this.leaderboards.set('boss_kills', {
|
|
name: 'Boss Kill Times',
|
|
entries: []
|
|
});
|
|
}
|
|
|
|
submitScore(leaderboardId, score) {
|
|
const leaderboard = this.leaderboards.get(leaderboardId);
|
|
if (!leaderboard) return false;
|
|
|
|
leaderboard.entries.push({
|
|
player: 'local_player',
|
|
score,
|
|
timestamp: Date.now()
|
|
});
|
|
|
|
// Sort by score (descending)
|
|
leaderboard.entries.sort((a, b) => b.score - a.score);
|
|
|
|
// Keep top 100
|
|
leaderboard.entries = leaderboard.entries.slice(0, 100);
|
|
|
|
console.log(`🏆 Score submitted to ${leaderboard.name}: ${score}`);
|
|
return true;
|
|
}
|
|
|
|
getLeaderboard(leaderboardId) {
|
|
return this.leaderboards.get(leaderboardId);
|
|
}
|
|
|
|
// ========== SOCIAL INTEGRATION ==========
|
|
|
|
shareScreenshot() {
|
|
console.log('📸 Screenshot shared!');
|
|
// Steam overlay integration
|
|
}
|
|
|
|
visitFarm(playerId) {
|
|
console.log(`🚜 Visiting ${playerId}'s farm...`);
|
|
}
|
|
|
|
sendGift(playerId, item, amount) {
|
|
const gift = {
|
|
id: `gift_${Date.now()}`,
|
|
from: 'local_player',
|
|
to: playerId,
|
|
item,
|
|
amount,
|
|
message: '',
|
|
sentAt: Date.now()
|
|
};
|
|
|
|
console.log(`🎁 Gift sent to ${playerId}: ${amount}x ${item}`);
|
|
return gift;
|
|
}
|
|
|
|
receiveGift(giftId) {
|
|
console.log(`🎁 Gift received: ${giftId}`);
|
|
|
|
// Add to inventory
|
|
if (this.scene.inventorySystem) {
|
|
// this.scene.inventorySystem.addItem(gift.item, gift.amount);
|
|
}
|
|
}
|
|
|
|
addFriend(playerId) {
|
|
this.friends.add(playerId);
|
|
console.log(`👥 Added friend: ${playerId}`);
|
|
this.saveProgress();
|
|
}
|
|
|
|
removeFriend(playerId) {
|
|
this.friends.delete(playerId);
|
|
console.log(`👋 Removed friend: ${playerId}`);
|
|
this.saveProgress();
|
|
}
|
|
|
|
// ========== COMMUNITY EVENTS ==========
|
|
|
|
defineEvents() {
|
|
this.events = {
|
|
'harvest_festival': {
|
|
name: 'Harvest Festival',
|
|
duration: 604800000, // 7 days
|
|
bonuses: { crop_yield: 2.0, xp: 1.5 }
|
|
},
|
|
'zombie_invasion': {
|
|
name: 'Zombie Invasion',
|
|
duration: 259200000, // 3 days
|
|
bonuses: { zombie_spawn: 3.0, loot: 2.0 }
|
|
},
|
|
'winter_wonderland': {
|
|
name: 'Winter Wonderland',
|
|
duration: 1209600000, // 14 days
|
|
bonuses: { snow_items: true, special_decorations: true }
|
|
}
|
|
};
|
|
}
|
|
|
|
startEvent(eventId) {
|
|
const event = this.events[eventId];
|
|
if (!event) return false;
|
|
|
|
this.activeEvent = {
|
|
id: eventId,
|
|
...event,
|
|
startTime: Date.now(),
|
|
endTime: Date.now() + event.duration
|
|
};
|
|
|
|
console.log(`🎉 Event started: ${event.name}`);
|
|
return true;
|
|
}
|
|
|
|
endEvent() {
|
|
if (!this.activeEvent) return;
|
|
|
|
console.log(`🎉 Event ended: ${this.activeEvent.name}`);
|
|
this.activeEvent = null;
|
|
}
|
|
|
|
// ========== SEASONAL CHALLENGES ==========
|
|
|
|
getWeeklyChallenges() {
|
|
return [
|
|
{ name: 'Harvest 500 crops', reward: { gold: 1000 } },
|
|
{ name: 'Defeat 50 zombies', reward: { xp: 500 } },
|
|
{ name: 'Craft 20 items', reward: { blueprint: 'rare_item' } }
|
|
];
|
|
}
|
|
|
|
getMonthlyChallenges() {
|
|
return [
|
|
{ name: 'Reach level 50', reward: { legendary_item: 1 } },
|
|
{ name: 'Complete all quests', reward: { title: 'Quest Master' } },
|
|
{ name: 'Defeat all bosses', reward: { mount: 'dragon' } }
|
|
];
|
|
}
|
|
|
|
completeChallenge(challengeId) {
|
|
console.log(`✅ Challenge completed: ${challengeId}`);
|
|
}
|
|
|
|
// ========== UPDATE ==========
|
|
|
|
update(delta) {
|
|
// Update active event
|
|
if (this.activeEvent) {
|
|
const now = Date.now();
|
|
if (now >= this.activeEvent.endTime) {
|
|
this.endEvent();
|
|
}
|
|
}
|
|
|
|
// Update market prices periodically
|
|
// this.updateMarketPrices();
|
|
}
|
|
|
|
// ========== PERSISTENCE ==========
|
|
|
|
saveProgress() {
|
|
const data = {
|
|
friends: Array.from(this.friends),
|
|
leaderboards: Array.from(this.leaderboards.entries()).map(([id, lb]) => ({
|
|
id,
|
|
entries: lb.entries
|
|
}))
|
|
};
|
|
|
|
localStorage.setItem('novafarma_multiplayer', JSON.stringify(data));
|
|
}
|
|
|
|
loadProgress() {
|
|
const saved = localStorage.getItem('novafarma_multiplayer');
|
|
if (saved) {
|
|
try {
|
|
const data = JSON.parse(saved);
|
|
this.friends = new Set(data.friends || []);
|
|
|
|
if (data.leaderboards) {
|
|
data.leaderboards.forEach(lb => {
|
|
const leaderboard = this.leaderboards.get(lb.id);
|
|
if (leaderboard) {
|
|
leaderboard.entries = lb.entries;
|
|
}
|
|
});
|
|
}
|
|
|
|
console.log('✅ Multiplayer progress loaded');
|
|
} catch (error) {
|
|
console.error('Failed to load multiplayer progress:', error);
|
|
}
|
|
}
|
|
}
|
|
|
|
destroy() {
|
|
this.saveProgress();
|
|
console.log('🌐 Multiplayer & Social System destroyed');
|
|
}
|
|
}
|